﻿using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
using Crossroad.Core.Data;
using Crossroad.Core.Configs;
using Crossroad.Core.Models;
using Crossroad.Core.Exceptions;
using Crossroad.OAuth.Model;
using Crossroad.Utils;
using Crossroad.Utils.Extensions;

namespace Crossroad.OAuth.Service.Impl
{
    /// <summary>
    /// oauth2.0授权客户端表
    /// </summary>
    public class ClientService : Access<Client>, IClientService
    {
        private readonly AccessTokenService accessTokenService;
        private readonly RefreshTokenService refreshTokenService;


        public ClientService(
            IAccessTokenService accessTokenServiceIpt,
            IRefreshTokenService refreshTokenServiceIpt
        )
        {
            accessTokenService = accessTokenServiceIpt as AccessTokenService;
            refreshTokenService = refreshTokenServiceIpt as RefreshTokenService;
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="method"></param>
        /// <param name="loadRelevantData">是否加载关联数据</param>
        public Pagination<Client> GetPaging(
            int pageIndex,
            int pageSize,
            Action<ISugarQueryable<Client>> method,
			bool loadRelevantData = true
        )
        {
            var query = db.Queryable<Client>();
            method(query);
            var totalCount = 0;
            var page = new Pagination<Client>
            {
                PageIndex = pageIndex,
                PageSize = pageSize,
            };
            page.Records = query.ToPageList(page.PageIndex, page.PageSize, ref totalCount);
            page.TotalCount = totalCount;
			if(loadRelevantData)
                Load(page.Records);

            return page;
        }

        /// <summary>
        /// 查询列表
        /// </summary>
        /// <param name="method"></param>
        /// <param name="loadRelevantData">是否加载关联数据</param>
        /// <returns></returns>
        public  List<Client> GetList(
            Action<ISugarQueryable<Client>> method,
			bool loadRelevantData = true
        )
        {
            var query = db.Queryable<Client>();
            method(query);
            var list = query.ToList();
			if(loadRelevantData)
				Load(list);

            return list;
        }

        /// <summary>
        /// 查询详情
        /// </summary>
        /// <param name="method"></param>
        /// <param name="loadRelevantData">是否加载关联数据</param>
        /// <returns></returns>
        public Client GetEntity(
            Action<ISugarQueryable<Client>> method,
			bool loadRelevantData = true
		)
        {
            var query = db.Queryable<Client>();
            method(query);
            var model = query.First();
            if (loadRelevantData)
                Load(model);

            return model;
        }

        /// <summary>
        /// 查询详情
        /// </summary>
        /// <param name="id"></param>
        /// <param name="loadRelevantData">是否加载关联数据</param>
        /// <returns></returns>
        public Client GetEntity(dynamic id, bool loadRelevantData = true)
        {
            var model = db.Queryable<Client>().InSingle(id);
            if (loadRelevantData)
                Load(model);

            return model;
        }

        /// <summary>
        /// 根据id列表查询maps
        /// </summary>
        /// <param name="idList"></param>
        /// <returns></returns>
        public Dictionary<string, Client> GetMaps(List<string> idList)
        {
            var maps = new Dictionary<string, Client>();
            if (idList.Count < 1)
                return maps;

            var list = db.Queryable<Client>()
                .In(f => f.clientId, idList.Distinct().ToArray())
                .ToList();

            list.ForEach(m =>
            {
                maps.Add(m.clientId, m);
            });

            return maps;
        }

        /// <summary>
        /// 新增返回详情
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public Client CreateAt(Client model)
        {
            model = db.Insertable(model).ExecuteReturnEntity();

            return GetEntity(model.clientId);
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="model"></param>
		public Client UpdateAt(Client model) 
		{
			var rows = db.Updateable(model).IgnoreColumns(true).ExecuteCommand();

			return GetEntity(model.clientId);
		}

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="source"></param>
        public void DeleteAt(Client source)
        {
             var rows = db.Deleteable<Client>().In(source.clientId).ExecuteCommand();
            if (rows < 1)
                throw new LogicException("删除失败！");
        }


		#region 加载关联数据

        public void Load(List<Client> list)
        {
            if (list.IsNull())
                return;
        }

        public void Load(Client model)
        {
            if (model.IsNull())
                return;
        }

        #endregion

        #region 业务逻辑

        /// <summary>
        /// 创建一个访问令牌
        /// </summary>
        /// <param name="appId">应用id</param>
        /// <param name="uid">用户id</param>
        /// <returns></returns>
        public object CreateToken(string appId, int uid)
        {
            //配置参数
            var option = OAuthConfig.Option;

            //客户端认证检测
            var client = GetEntity(queryable => 
                queryable.Where(a => a.clientId.Equals(option.ClientId) && a.clientSecret.Equals(option.ClientSecret))
            );
            if (client.IsNull())
                throw new LogicException("客户端不存在");

            BeginTran();
            try
            {
                //根据userId创建一个新的访问令牌
                var access = accessTokenService.CreateAt(new AccessToken
                {
                    accessToken = KeyUtil.UniqueKey,
                    clientId = option.ClientId,
                    scope = appId,
                    userId = uid.ToString(),
                    /*
                     * 单位(秒)
                     * 当前系统时间戳 + (秒 x 分钟 x 小时)
                     */
                    expires = DateTime.Now.ToTimeStamp() + (60 * 60 * option.AccessTokenExpires),
                });
                //根据uid创建一个新的刷新令牌
                var refresh = refreshTokenService.CreateAt(new RefreshToken
                {
                    refreshToken = KeyUtil.UniqueKey,
                    clientId = option.ClientId,
                    scope = appId,
                    userId = uid.ToString(),
                    /*
                     * 单位(秒)
                     * 当前系统时间戳 + (秒 x 分钟 x 小时)
                     */
                    expires = DateTime.Now.ToTimeStamp() + (60 * 60 * option.RefreshTokenExpires),
                });
                CommitTran();

                return new
                {
                    access = new
                    {
                        access.clientId,
                        access.accessToken,
                        access.expires,
                        access.expiresText,
                    },
                    refresh = new
                    {
                        refresh.clientId,
                        refresh.refreshToken,
                        refresh.expires,
                        refresh.expiresText,
                    },
                };
            }
            catch (Exception e)
            {
                RollbackTran();
                throw new LogicException(e.Message);
            }
        }

        #endregion

    }
}
